package com.icinfo.cloud.provider.punish.common.datareport.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.enums.YesOrNoEnum;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.common.utils.BaseUtil;
import com.icinfo.cloud.provider.common.utils.SpringContextUtil;
import com.icinfo.cloud.provider.punish.common.datareport.dto.CaseDataReportRecordQueryDto;
import com.icinfo.cloud.provider.punish.common.datareport.dto.CaseDataReportRequestCommonDto;
import com.icinfo.cloud.provider.punish.common.datareport.enums.CaseDataReportOptTypeEnum;
import com.icinfo.cloud.provider.punish.common.datareport.enums.ReportDataTypeEnum;
import com.icinfo.cloud.provider.punish.common.datareport.service.ICaseDataReportRecordService;
import com.icinfo.cloud.provider.punish.common.datareport.service.ICaseDataReportService;
import com.icinfo.cloud.provider.punish.common.datareport.service.ICaseDataReportStageInfoService;
import com.icinfo.cloud.provider.punish.common.datareport.vo.CaseDataReportRecordVo;
import com.icinfo.cloud.provider.punish.ucase.casemain.dto.CaseMainDetailAuxiliaryInfoRequest;
import com.icinfo.cloud.provider.punish.ucase.casemain.dto.CasePartiesRecordQueryDto;
import com.icinfo.cloud.provider.punish.ucase.casemain.enums.CaseTypeEnum;
import com.icinfo.cloud.provider.punish.ucase.casemain.enums.HandleTypeEnum;
import com.icinfo.cloud.provider.punish.ucase.casemain.enums.PartiesReasonTypeEnum;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainDetailAuxiliaryInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainDetailInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainDetailSimpleInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.*;
import com.icinfo.cloud.provider.punish.ucase.casemain.vo.CaseMainInfoVo;
import com.icinfo.cloud.provider.punish.ucase.casemain.vo.CasePartiesInfoVo;
import com.icinfo.framework.common.web.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 描述：案件数据上报接口实现类-处罚执行信息
 *
 * @author xiangyuyu
 * @date 2022/6/13 20:04
 */
@Slf4j
@Service
public class CaseDataReportExecuteServiceImpl implements ICaseDataReportService {
    private static final String TERRITORY_CODE_PREFIX = "001";
    /**
     * 行政处罚执行推送接口
     */
    private static final String EXECUTE_HTTP = "ydz5c15I5aVW4ru2.htm";
    @Resource
    private ICaseMainDetailInfoService caseMainDetailInfoService;
    @Resource
    private ICaseMainInfoService caseMainInfoService;
    @Resource
    private ICaseDataReportStageInfoService caseDataReportStageInfoService;
    @Resource
    private ICaseDataReportRecordService caseDataReportRecordService;
    @Resource
    private CaseDataReportBasicServiceImpl basicService;
    @Resource
    private ICasePartiesRecordService casePartiesRecordService;
    @Resource
    private ICaseMainDetailAuxiliaryInfoService caseMainDetailAuxiliaryInfoService;
    @Resource
    private ICaseMainDetailSimpleInfoService caseMainDetailSimpleInfoService ;

    /**
     * 描述：收集数据上报-执行信息
     *
     * @param caseMainInfoVo {@link CaseMainInfoVo}
     * @param reportDataType 上报数据类型
     * @param isUpdateReReport 是否更新补推
     * @param partyInfo {@link CasePartiesInfoVo} 当事人信息
     * @param optType          更新类型
     * @return {@link JSONObject} 上报数据内容
     * @author xiangyuyu
     * @date 2022-03-31 23:18
     */
    @Override
    public JSONObject reportDataCollect(CaseMainInfoVo caseMainInfoVo, String reportDataType,boolean isUpdateReReport,CasePartiesInfoVo partyInfo, String optType) {
        JSONObject returnInfo = new JSONObject();
        log.info("collectReportCaseDecisionInfo start...param-caseMainInfo:{},reportDataType:{}", caseMainInfoVo, reportDataType);
        JSONObject executeInfo = new JSONObject();
        String caseId = caseMainInfoVo.getId();
        String caseTerritoryCode = caseMainInfoVo.getCaseTerritoryCode();
        String sourceDeptCode = TERRITORY_CODE_PREFIX + caseTerritoryCode;
        CaseDataReportRecordQueryDto queryDto = new CaseDataReportRecordQueryDto();
        String partyId = partyInfo.getPartyId();
        queryDto.setCaseId(caseId);
        queryDto.setReportDataType(reportDataType);
        queryDto.setIsTestData(YesOrNoEnum.YES.getCode());
        queryDto.setPartyId(partyId);
        //默认测试数据1
        String envFlag = Constant.STRING_1;
        if (SpringContextUtil.checkIsPrdProfile()) {
            queryDto.setIsTestData(YesOrNoEnum.NO.getCode());
            envFlag = Constant.STRING_0;
        }

        List<CaseDataReportRecordVo> list = caseDataReportRecordService.getCaseDataReportRecord(queryDto);
        String reportActionType = "I";
        if (!ObjectUtils.isEmpty(list) && list.size() > 0) {
            CaseDataReportRecordVo latestRecord = list.get(Constant.INTEGER_0);
            String latestReportResult = latestRecord.getReportResult();
            if (!Constant.STRING_0.equals(latestReportResult)) {
                String oriActionType = latestRecord.getReportActionType();
                reportActionType = "U".equals(oriActionType) ? oriActionType : "I";
            } else {
                reportActionType = "U";
            }
        }
        String caseType = caseMainInfoVo.getCaseType();
        //获取案件详细信息
        CaseMainDetailInfo caseMainDetailInfo;
        CaseMainDetailSimpleInfo caseMainDetailSimpleInfo = null;
        if(CaseTypeEnum.SIMPLE_PROCEDURE.getCode().equals(caseType)){
            //简易处罚
            caseMainDetailInfo = new CaseMainDetailInfo();
            caseMainDetailSimpleInfo = caseMainDetailSimpleInfoService.getCaseMainDetailSimpleInfo(caseId);
            if(ObjectUtils.isEmpty(caseMainDetailSimpleInfo)){
                throw new BusinessException("未匹配到简易处罚的案件详情信息-caseId:"+caseId);
            }
        } else {
            //TODO：目前暂时将简易处罚之外的案件的宽表数据认为存储在case_main_detail_info,后期如果有新增宽表，得特殊处理
            caseMainDetailInfo = caseMainDetailInfoService.getCaseMainDetailByCaseId(caseId);
        }
        executeInfo.put("recordUniqueIdentity", BaseUtil.createUid());

        /*
            如果当事人id为空，则说明是单当事人/多当事人合并处罚，
            则caseId作为 punishBaseInfoCode，
            否则取当事人id作为 punishBaseInfoCode
         */
        String uid = partyId;
        //是否是多当事人分别处罚
        boolean isMultiplePartiesAndPartPunish = !ObjectUtils.isEmpty(partyId)?true:false;
        //处罚执行相关信息获取
        String executeWay = null;
        String punishContent = null;
        LocalDate executeFinishDate;
        String executeConditionDesc;
        if(!isMultiplePartiesAndPartPunish){
            uid = caseId;
            executeWay = caseMainDetailInfo.getExecuteWay();
            punishContent = caseMainDetailInfo.getPunishContent();
            executeFinishDate = caseMainDetailInfo.getExecuteFinishDate();
            executeConditionDesc = caseMainDetailInfo.getExecuteConditionDesc();
        } else {
            //获取案件详情补充表信息
            CaseMainDetailAuxiliaryInfoRequest request = new CaseMainDetailAuxiliaryInfoRequest(caseId,partyId);
            List<CaseMainDetailAuxiliaryInfo> caseMainDetailAuxiliaryList = caseMainDetailAuxiliaryInfoService.getCaseMainDetailAuxiliaryInfo(request);
            if(!ObjectUtils.isEmpty(caseMainDetailAuxiliaryList) && caseMainDetailAuxiliaryList.size() > 0){
                CaseMainDetailAuxiliaryInfo caseMainDetailAuxiliaryInfo = caseMainDetailAuxiliaryList.get(Constant.INTEGER_0);
                executeWay = caseMainDetailAuxiliaryInfo.getExecuteWay();
                punishContent = caseMainDetailAuxiliaryInfo.getPunishContent();
                executeFinishDate = caseMainDetailAuxiliaryInfo.getExecuteFinishDate();
                executeConditionDesc = caseMainDetailAuxiliaryInfo.getExecuteConditionDesc();
            } else {
                executeFinishDate = LocalDate.now();
                executeConditionDesc = Constant.STRING_HORIZONTAL_BARS;
            }
        }
        if(!ObjectUtils.isEmpty(caseMainDetailSimpleInfo)){
            //简易处罚
            executeWay = "自觉履行";
            executeFinishDate = caseMainInfoVo.getCaseEndTime().toLocalDate();
            executeConditionDesc = Constant.STRING_HORIZONTAL_BARS;
        }
        executeInfo.put("punishBaseInfoCode", uid);
        String executionType = Constant.STRING_1;
        String isExecute = Constant.STRING_0;
        if (!ObjectUtils.isEmpty(executeWay)) {
            /*
            系统数据：
            中文
            数据上报规则：
                1：自觉履行
                2：强制执行
             */
            if ("强制执行".equals(executeWay)) {
                executionType = Constant.STRING_2;
            }
            executeInfo.put("executionType", executionType);
            isExecute = Constant.STRING_1;

        }
        executeInfo.put("isExecute", isExecute);
        String casePunishContent = ObjectUtils.isEmpty(punishContent) ? "-" : punishContent;
        executeInfo.put("penaltyResult", casePunishContent);
        //是否分期（数据上报规则：0-否/1-是）
        //是否延期 FIXME: 2022/4/2 目前无该流程，暂定否
        executeInfo.put("isStaging", Constant.STRING_0);
        //（数据上报规则：0-否/1-是）
        // FIXME: 2022/4/2 目前无该流程，暂定否
        executeInfo.put("isExtention", Constant.STRING_0);
        if (YesOrNoEnum.YES.getCode().equals(isExecute)) {
            executeInfo.put("executionFinishDate", executeFinishDate);
        } else {
            executeInfo.put("noExecutionReason", executeConditionDesc);
        }
        executeInfo.put("optType", !ObjectUtils.isEmpty(optType) ? optType :reportActionType);
        executeInfo.put("envFlag", envFlag);
        executeInfo.put("sourceDeptCode", sourceDeptCode);
        returnInfo.put("executeInfo", executeInfo);
        //到dataReport时清空该键值
        returnInfo.put("reportActionType", !ObjectUtils.isEmpty(optType)?optType:reportActionType);
        returnInfo.put("envFlag", envFlag);
        log.info("collectReportCaseExecuteInfo end...result-returnInfo", returnInfo);
        return returnInfo;
    }


    /**
     * 描述：数据上报-execute
     *
     * @param dto          {@link CaseDataReportRequestCommonDto}
     * @param partyInfo    {@link CasePartiesInfoVo} 当事人信息
     * @param caseMainInfo {@link CaseMainInfoVo} 案件主体信息
     * @return {@link Result<String>} 上报结果
     * @author xiangyuyu
     * @date 2022-03-30 21:23
     */
    @Override
    public Result<String> singleCaseReport(CaseDataReportRequestCommonDto dto, CasePartiesInfoVo partyInfo, CaseMainInfoVo caseMainInfo) {
        log.info("dataReportExecute start... dto:{}", dto);
        String caseId = dto.getCaseId();
        String optType = dto.getOptType();
        if(!ObjectUtils.isEmpty(optType)){
            if(!CaseDataReportOptTypeEnum.isLegalEnumCode(optType)){
                throw new BusinessException("请指定有效的数据上报更新类型枚举(I：新增， U：修改； D：删除)");
            }
        }
        if (!caseDataReportRecordService.personalCheckIsAllowDataReport(caseId, null)) {
            log.info("该案件暂不开启数据上报-caseId:{}", caseId);
            return Result.error("该案件暂不开启数据上报-caseId:" + caseId);
        }
        List<CasePartiesInfoVo> partiesInfo = new ArrayList<>();
        if (ObjectUtils.isEmpty(partyInfo)) {
            //获取当事人信息
            if (ObjectUtils.isEmpty(caseMainInfo)) {
                caseMainInfo = caseMainInfoService.getCaseMainInfo(caseId);
            }
            String casePartiesReasonType = caseMainInfo.getCasePartiesReasonType();
            String handleType = caseMainInfo.getHandleType();
            CasePartiesRecordQueryDto queryDto = new CasePartiesRecordQueryDto(caseId, null, YesOrNoEnum.NO.getCode());
            partiesInfo = casePartiesRecordService.getCasePartiesInfoList(queryDto);
            if (!(PartiesReasonTypeEnum.MULTIPLE_PARTIES.getCode().equals(casePartiesReasonType)
                    && HandleTypeEnum.PART_PUNISH.getCode().equals(handleType))
            ) {
                //只取第一个当事人信息
                List<CasePartiesInfoVo> tmp = new ArrayList<>();
                tmp.add(partiesInfo.get(Constant.INTEGER_0));
                partiesInfo = tmp;
                partiesInfo.forEach(p -> p.setPartyId(null));
            }
        } else {
            partiesInfo.add(partyInfo);
        }
        for (CasePartiesInfoVo p : partiesInfo) {
            String partyId = p.getPartyId();
            try {
                if (caseDataReportRecordService.getIsAllowDataReport(caseId)) {
                    String errorMsg = "";
                    if(ObjectUtils.isEmpty(caseMainInfo)){
                        //根据案件id查询案件信息
                        caseMainInfo = caseMainInfoService.getCaseMainInfo(caseId);
                    }
                    String uri = EXECUTE_HTTP;
                    String reportDataType = ReportDataTypeEnum.EXECUTE.getCode();
                    JSONObject tmpData = reportDataCollect(caseMainInfo, reportDataType, false, p, optType);
                    JSONObject reportData = new JSONObject(8);
                    reportData.put("reportActionType", !ObjectUtils.isEmpty(optType)?optType:tmpData.get("reportActionType"));
                    reportData.put("envFlag", tmpData.get("envFlag"));
                    tmpData.remove("envFlag");
                    tmpData.remove("reportActionType");
                    reportData.put("executeInfo", tmpData);
                    Map<String, String> params = new HashMap<>(20);
                    for (Map.Entry<String, Object> e : reportData.entrySet()) {
                        params.put(e.getKey(), (ObjectUtils.isEmpty(e.getValue()) ? "" : e.getValue().toString()));
                    }
                    errorMsg = caseDataReportRecordService.dataReport(uri, reportDataType, params, caseMainInfo);
                    log.info("dataReportExecute end");
                    if (ObjectUtils.isEmpty(errorMsg)) {
                        caseDataReportStageInfoService.dealAfterReport(caseId, true, ReportDataTypeEnum.EXECUTE.getCode(), null,partyId);
                    } else {
                        if(errorMsg.contains(Constant.STRING_RECORD_EXISTS)){
                            caseDataReportStageInfoService.dealAfterReport(caseId, true, ReportDataTypeEnum.EXECUTE.getCode(), errorMsg,partyId);
                        } else if(errorMsg.contains(Constant.STRING_ERROR_SIGN)) {
                            caseDataReportRecordService.reportAgain(dto, partyInfo, caseMainInfo, this, reportDataType);
                        } else {
                            caseDataReportStageInfoService.dealAfterReport(caseId, false, ReportDataTypeEnum.EXECUTE.getCode(), errorMsg,partyId);
                        }
                        return Result.error(errorMsg);
                    }
                } else {
                    String tmpMsg = "该部门是否允许上报数据按钮处于关闭状态,caseId:" + caseId;
                    throw new BusinessException(tmpMsg);
                }
            } catch (Exception e) {
                e.printStackTrace();
                caseDataReportStageInfoService.dealAfterReport(caseId, false, ReportDataTypeEnum.EXECUTE.getCode(), e.getMessage(),partyId);
                return Result.error("dataReportExecute catch exception：" + e.getMessage());
            }

        }
        return Result.success("上报成功");
    }

    /**
     * 【V2.0.0】描述：处罚执行信息-数据批量上报
     * @param baseInfoReportFailCaseIdList 上报失败的案件id列表
     * @return 上报失败案件id列表
     * @author xiangyuyu
     * @date 2022-06-13 16:02
     */
    @Override
    public List<String> batchCaseReport(List<String> baseInfoReportFailCaseIdList) {
        if(ObjectUtils.isEmpty(baseInfoReportFailCaseIdList)){
            baseInfoReportFailCaseIdList = new ArrayList<>();
        }
        LocalDateTime startTime = LocalDateTime.now();
        log.info("basicInfoReport start-startTime:{}", startTime);

        //5、查看2天前是否存在"处罚执行完毕"的案件
        List<String> shouldUploadPunishExecuteInfo = caseMainDetailInfoService.getCaseIdListShouldReportExecuteInfo();
        if (!ObjectUtils.isEmpty(shouldUploadPunishExecuteInfo) && shouldUploadPunishExecuteInfo.size() > 0) {
            log.info("决定执行完毕数量:{}", shouldUploadPunishExecuteInfo.size());
            List<String> finalBaseInfoReportFailCaseIdList = baseInfoReportFailCaseIdList;
            shouldUploadPunishExecuteInfo.forEach(e -> {
                if (!finalBaseInfoReportFailCaseIdList.contains(e)) {
                    CaseMainInfoVo caseMainInfo = caseMainInfoService.getCaseMainInfo(e);
                    if (!caseDataReportRecordService.personalCheckIsAllowDataReport(e, caseMainInfo)) {
                        return;
                    }
                    String casePartiesReasonType = caseMainInfo.getCasePartiesReasonType();
                    String handleType = caseMainInfo.getHandleType();
                    CasePartiesRecordQueryDto queryDto = new CasePartiesRecordQueryDto(e,null,YesOrNoEnum.NO.getCode());
                    List<CasePartiesInfoVo> partiesInfo = casePartiesRecordService.getCasePartiesInfoList(queryDto);
                    if (!(PartiesReasonTypeEnum.MULTIPLE_PARTIES.getCode().equals(casePartiesReasonType)
                            && HandleTypeEnum.PART_PUNISH.getCode().equals(handleType))
                    ) {
                        //只取第一个当事人信息
                        List<CasePartiesInfoVo> tmp = new ArrayList<>();
                        tmp.add(partiesInfo.get(Constant.INTEGER_0));
                        partiesInfo = tmp;
                        partiesInfo.forEach(p->p.setPartyId(null));
                    }
                    CaseDataReportRequestCommonDto dto = new CaseDataReportRequestCommonDto();
                    dto.setCaseId(e);
                    for (CasePartiesInfoVo partyInfo : partiesInfo) {
                        String partyId = partyInfo.getPartyId();
                        //校验是否需要上报
                        boolean isShouldReport = caseDataReportStageInfoService.checkIsShouldReport(ReportDataTypeEnum.EXECUTE.getCode(), e,partyId);
                        if (isShouldReport) {
                            //判断案件基础信息是否上报
                            if (!caseDataReportStageInfoService.checkStageInfoIsReportSuccess(ReportDataTypeEnum.BASE.getCode(), e,partyId)) {
                                Result<String> result = basicService.singleCaseReport(dto,partyInfo,caseMainInfo);
                                if (!caseDataReportRecordService.analyseResultToJudgeIsReportSuccess(result)) {
                                    finalBaseInfoReportFailCaseIdList.add(e);
                                } else {
                                    singleCaseReport(dto,partyInfo,caseMainInfo);
                                }
                            } else {
                                singleCaseReport(dto,partyInfo,caseMainInfo);
                            }
                        }
                    }


                }
            });
        } else {
            log.info("date:{},无决定执行完毕",startTime);
        }

        LocalDateTime endTime = LocalDateTime.now();
        Duration duration = Duration.between(startTime, endTime);
        long seconds = duration.getSeconds();
        log.info("basicInfoReport end-endTime:{},consume:{} s", endTime, seconds);
        return baseInfoReportFailCaseIdList;
    }

    /**
     * 描述：单个案件重新数据上报（U）
     *
     * @param caseId 案件id
     * @param partyInfo    {@link CasePartiesInfoVo} 当事人信息
     * @param caseMainInfo {@link CaseMainInfoVo} 案件主体信息
     * @return {@link Result <String>} 上报结果
     * @author xiangyuyu
     * @date 2022-06-13 18:52
     */
    @Override
    public Result<String> singleCaseReportAgain(String caseId, CasePartiesInfoVo partyInfo, CaseMainInfoVo caseMainInfo) {
        return null;
    }

    /**
     * 描述：批量案件重新数据上报（U）
     *
     * @return {@link Result <String>} 上报失败案件id列表
     * @author xiangyuyu
     * @date 2022-06-13 18:52
     */
    @Override
    public List<String> batchCaseReportAgain() {
        return null;
    }
}
